﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

using CTP.CRM.Core.CurrentUs.Dtos;
using CTP.CRM.Core.SharedModel.InternalCore.Token;
using CTP.CRM.Core.SharedModel.Pub;
using Volo.Abp;
using CTP.CRM.Core.SharedModel;

namespace CTP.CRM.Core.Common.SharedModel.Pub
{
    public sealed class ReqHeaderResolveHelper
    {
        private static ISecurityKeyProvider _securityKeyProvider = new DefaultSecurityKeyProvider();

        private static readonly string ENV = CTPABPCore.Configuration["Environment"];

        //
        // 摘要:
        //     Retrieves the user information associated with the current request.
        //
        // 参数:
        //   key:
        //     Optional: The key used for decoding the authorization token.
        //
        // 返回结果:
        //     The user information.
        public static CurrentUser GetRequestUserInfo(string key = null)
        {
            HttpContext httpContext = CTPABPCore.HttpContext;
            if (httpContext == null)
            {
                return CreateDefaultSystemUser();
            }

            if (httpContext.Request.Headers.Keys.Contains("SystemRequest") || !httpContext.Request.Headers.Keys.Contains("Authorization"))
            {
                return CreateDefaultSystemUser();
            }

            ClaimsPrincipal claimsPrincipal = null;
            try
            {
                claimsPrincipal = Decode(httpContext.Request.Headers["Authorization"], key ?? _securityKeyProvider.GetSecurityKey(ENV));
            }
            catch (Exception)
            {
                throw new BusinessException("401", "解析Token失败，请重新登录!");
            }

            if (claimsPrincipal == null)
            {
                throw new BusinessException("401", "未找到相关的用户身份信息!");
            }

            return BuildUserFromClaims(claimsPrincipal);
        }

        public static CurrentUser BuildUserFromClaims(ClaimsPrincipal claimsPrincipal)
        {
            ThrowHelper.ThrowIfCodition(claimsPrincipal == null, "解析Token失败,请检查Token是否过期或被篡改!", "BuildUserFromClaims", 58, "claimsPrincipal is null");
            CurrentUser currentUser = new CurrentUser();
            try
            {
                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.UserId))
                {
                    string value = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.UserId).Value;
                    ThrowHelper.ThrowIfEmpty(value, "用户信息解析失败，缺少用户Id!", "BuildUserFromClaims", 66, "userId");
                    currentUser.UserId = Convert.ToInt32(value);
                }

                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.EmpId))
                {
                    string value2 = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.EmpId).Value;
                    if (!string.IsNullOrEmpty(value2))
                    {
                        currentUser.EmployeeId = Convert.ToInt32(value2);
                    }
                }

                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.SystemId))
                {
                    string value3 = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.SystemId).Value;
                    if (!string.IsNullOrEmpty(value3))
                    {
                        currentUser.SystemId = Convert.ToInt32(value3);
                    }
                }

                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.ExternalSubjectId))
                {
                    string value4 = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.ExternalSubjectId).Value;
                    if (!string.IsNullOrEmpty(value4))
                    {
                        currentUser.ExternalMainId = Convert.ToInt32(value4);
                    }
                }

                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.ExternalSubjectName))
                {
                    string value5 = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.ExternalSubjectName).Value;
                    if (!string.IsNullOrEmpty(value5))
                    {
                        currentUser.ExternalMainName = value5;
                    }
                }

                if (claimsPrincipal.HasClaim((Claim x) => x.Type == UserCenterClaimTypes.TokenOrigin))
                {
                    string value6 = claimsPrincipal.FindFirst((Claim x) => x.Type == UserCenterClaimTypes.TokenOrigin).Value;
                    if (!string.IsNullOrEmpty(value6))
                    {
                        currentUser.TokenOrigin = value6;
                    }
                }
            }
            catch (Exception)
            {
                throw new BusinessException("401", "生成策略变更，请重新登录!");
            }

            return currentUser;
        }

        //
        // 摘要:
        //     Parse the final result
        //
        // 参数:
        //   token:
        //
        //   key:
        public static ClaimsPrincipal Decode(string token, string key)
        {
            return ServiceProviderServiceExtensions.GetRequiredService<ITokenValidator>(UserCenterServiceProvider.Instance).Validator(key, token).ClaimsPrincipal;
        }

        public static ClaimsPrincipal VerfiyToken(string token)
        {
            return Decode(token, _securityKeyProvider.GetSecurityKey(ENV));
        }

        public static CurrentUser CreateDefaultSystemUser()
        {
            return new CurrentUser
            {
                EmployeeId = 6000,
                UserId = 6000
            };
        }

        public static int ExtractBusinessIdOrSubSystemId(string target)
        {
            ThrowHelper.ThrowIfNull(CTPABPCore.HttpContext, "Failed to retrieve HttpContext, error occurred at FindBusinessIdAndSubSystemId ", "ExtractBusinessIdOrSubSystemId", 145, "CTPABPCore.HttpContext");
            try
            {
                ThrowHelper.ThrowIfNotCodition(int.TryParse(CTPABPCore.HttpContext.Request.Headers[target], out var result), "Failed to retrieve " + target + " from the current request.", "ExtractBusinessIdOrSubSystemId", 156, "canConvert");
                return result;
            }
            catch (Exception)
            {
                throw new BusinessException(null, "Error retrieving " + target + ", please check if the calling party carries the corresponding parameter.");
            }
        }
    }
}
